package de.akabahn.ebd.stw.zdxfc.prs.tco.elemente;

import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.BIT0;
import static de.akabahn.ebd.stw.zdxfc.prs.ZDXFCConstants.BIT1;
import static de.akabahn.ebd.stw.zdxfc.prs.tco.ZDXFCTcoConstants.SIGNAL_HALTMELDER_AUS;
import static de.akabahn.ebd.stw.zdxfc.prs.tco.ZDXFCTcoConstants.SIGNAL_VERSCHLUSSMELDER_AN;
import static de.akabahn.ebd.stw.zdxfc.prs.tco.ZDXFCTcoConstants.SIGNAL_VERSCHLUSSMELDER_AUS;

import java.awt.Color;
import java.awt.Graphics;

/**
 * Implementierung des <code>Signalmelders</code>.<br>
 * <br>
 * Bitcodierung des Signal-Haltmelders<br>
 * <pre>
 * BIT1 BIT0  BEDEUTUNG
 *    0    0  AUS
 *    0    1  ROT AN
 *    1    0  ROT BLINKT
 * </pre>
 * <br>
 * Bitcodierung des Signal-Verschlussmelders<br>
 * <pre>
 * BIT1 BIT0  BEDEUTUNG
 *    0    0  AUS
 *    0    1  WEISS AN
 *    1    0  WEISS BLINKT
 * </pre>
 *   
 * @author Peter Eimann
 * @since 1.0
 * @version 1.1
 */
public abstract class Signal {

	private String[] id;

	protected Color haltMelderFarbe;
	protected String label;
	protected int startX;
	protected int startY;
	protected int ausleuchtungHaltmelder;
	protected int ausleuchtungVerschlussmelder;
	protected boolean verschlussZAp;
	protected boolean verschlussEPa;
	protected boolean blinkTaktAn;
	protected boolean blinkt;
	
	/**
	 * Intialisierung des Signalmelders mit den uebergebenen Eigenschaften
	 * 
	 * @param id Eindeutige IDs (Haltmelder und Verschlussmelder) des Signals
	 * @param label Signalbezeichnung
	 * @param startX X-Koordinate des Startpunkts des Signals
	 * @param startY Y--Koordinate des Startpunkts des Signals
	 * @param haltMelderFarbe Farbe des Haltmelders (C oder Cv)
	 * @param verschlussZAp Signal hat einen Verschlussmelder Zone d'Approche
	 * @param verschlussEPa Signal hat einen Verschlussmelder Enclenchement parcours
	 */
	public Signal(String[] id, String label, int startX, int startY, Color haltMelderFarbe, boolean verschlussZAp, boolean verschlussEPa) {
		this.id = id;
		this.label = label;
		this.startX = startX;
		this.startY = startY;
		this.haltMelderFarbe = haltMelderFarbe;
		this.verschlussZAp = verschlussZAp;
		this.verschlussEPa = verschlussEPa;
	}

	/**
	 * Gibt den bitcodierten Wert der Ausleuchtung des Haltmelders zurueck
	 * 
	 * @return Die Ausleuchtung
	 */
	public int getAusleuchtungHaltmelder() {
		return ausleuchtungHaltmelder;
	}

	/**
	 * Setzt den bitcodierten Wert der Ausleuchtung des Haltmelders
	 * 
	 * @param ausleuchtungHaltmelder Die Ausleuchtung
	 */
	public void setAusleuchtungHaltmelder(int ausleuchtungHaltmelder) {
		this.ausleuchtungHaltmelder = ausleuchtungHaltmelder;
	}

	/**
	 * Gibt den bitcodierten Wert der Ausleuchtung des Verschlussmelders zurueck
	 * 
	 * @return Die Ausleuchtung
	 */
	public int getAusleuchtungVerschlussmelder() {
		return ausleuchtungVerschlussmelder;
	}

	/**
	 * Setzt den bitcodierten Wert der Ausleuchtung des Verschlussmelders
	 * 
	 * @param ausleuchtungVerschlussmelder Die Ausleuchtung
	 */
	public void setAusleuchtungVerschlussmelder(int ausleuchtungVerschlussmelder) {
		this.ausleuchtungVerschlussmelder = ausleuchtungVerschlussmelder;
	}

	/**
	 * Wechselt den aktuellen Blink-Takt
	 */
	public void toggleBlinkTakt() {
		blinkTaktAn = !blinkTaktAn;
	}
	
	/**
	 * Gibt zurueck, ob ein Melder des Signals blinkt
	 * 
	 * @return <code>true</code> - Ein Melder des Signals blinkt
	 */
	public boolean isBlinkt() {
		return blinkt;
	}

	/**
	 * Gibt die ID des Elements an
	 * 
	 * @return die ID
	 */
	public String[] getId() {
		return id;
	}

	/**
	 * Zeichnen des Signals mit den Farben des Ausleuchtungszustands der Halt- und
	 * Verschlussmelder (muss in der konkreten Signal-Klasse implementiert werden)
	 * 
	 * @param g Der Grafik-Kontext
	 */
	public abstract void paint(Graphics g);
	
	/**
	 * Gibt die Farbe des Haltmelders anhand der aktuellen Ausleuchtung (an, aus) zurueck
	 * 
	 * @return Die Farbe des Haltmelders
	 */
	protected Color getColorHaltmelder() {
		if ((ausleuchtungHaltmelder & BIT0) == BIT0) {
			return haltMelderFarbe;
		} else {
			return SIGNAL_HALTMELDER_AUS;
		}
	}
	
	/**
	 * Gibt die Farbe des Verschlussmelders anhand der aktuellen Ausleuchtung (an, aus) zurueck.
	 * Soll der Verschlussmelder blinken, wird die Farbe aufgrund des aktuellen Blink-Takts
	 * zurueckgegeben.
	 * 
	 * @return Die Farbe des Verschlussmelders
	 */
	protected Color getColorVerschlussmelder() {
		if ((ausleuchtungVerschlussmelder & BIT0) == BIT0) {
			blinkt = false;
			return SIGNAL_VERSCHLUSSMELDER_AN;
		} else if ((ausleuchtungVerschlussmelder & BIT1) == BIT1) {
			blinkt = true;
			return blinkTaktAn ? SIGNAL_VERSCHLUSSMELDER_AN : SIGNAL_VERSCHLUSSMELDER_AUS;
		} else {
			blinkt = false;
			return SIGNAL_VERSCHLUSSMELDER_AUS;
		}
	}
}
